package com.fz.aop.log;

import com.fz.entity.log.SysOperLog;
import com.fz.entity.system.User;
import com.fz.mapper.log.SysOperLogMapper;
import com.fz.security.utils.SecurityUtils;
import com.fz.utils.IpUtils;
import com.fz.utils.JacksonUtils;
import com.fz.utils.StringUtils;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 *  运营平台操作日志
 */
@Component
@Aspect
@SuppressWarnings("unchecked")
public class UserOperLogAspect  {

    @Resource
    private SysOperLogMapper sysOperLogMapper;


    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 定义切点 排除登录和获取验证码之外的所有controller接口
     */
    @Pointcut("!execution(* com.fz.controller.system.LoginController.login*(..)) " +
            "&& !execution(* com.fz.controller.system.LoginController.randCode*(..)) " +
            "&& execution(* com.fz.controller..*(..))")
    public void operationPointCut() {

    }

    @Before("operationPointCut()")
    public void doBefore() throws Throwable {
        startTime.set(System.currentTimeMillis());
    }

    @AfterReturning("operationPointCut()")
    public void afterReturn(JoinPoint joinPoint) throws Throwable {
        //计算接口耗时
        Long time = System.currentTimeMillis() - startTime.get();
        //获取request
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        //保存操作日志
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //获取方法路径
        String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
        //获取整体参数
        String params = "";
        //参数值
        Object[] argValues = joinPoint.getArgs();
        //参数名称
        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
        if(argValues != null){
            for (int i = 0; i < argValues.length; i++) {
                if(StringUtils.checkRes(argNames[i])){
                    params = params + " "+ argNames[i] + ": " + JacksonUtils.obj2String(argValues[i]) + ",";
                }
            }
        }
        //获取ApiOperation的值 -- 接口描述
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        String apiOperationValue = apiOperation.value();
        //获取登录的用户名
        User user = SecurityUtils.getCurrentUser();
        String loginid = "" ;
        if(user != null){
            loginid = user.getLoginId();
        }
        //获取请求ip
        String requestIp = IpUtils.getIpAddr(request);
        //获取ip所属地
        String ipAddress = IpUtils.getCityInfo(requestIp);
        //获取浏览器
        String browser = IpUtils.getBrowser(request);

        SysOperLog sysOperLog = new SysOperLog();
        sysOperLog.setLoginId(loginid);
        if(StringUtils.isNotEmpty(params)){
            params = params.substring(0,params.length() - 1);
        }
        sysOperLog.setParam("{ "+params + " }");
        sysOperLog.setMethod(methodName);
        sysOperLog.setDescription(apiOperationValue);
        sysOperLog.setRequestIp(requestIp);
        sysOperLog.setTime(time.toString());
        sysOperLog.setIpAddress(ipAddress);
        sysOperLog.setBrowser(browser);
        sysOperLogMapper.insert(sysOperLog);
    }

}
